package com.woniu.zsd.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import com.woniu.client.PermissionClient;
import com.woniu.client.UserClient;
import com.woniu.client.dto.UserAddress;
import com.woniu.dto.SiteListDto;
import com.woniu.commons.util.DateUtils;
import com.woniu.commons.util.RedisKey;
import com.woniu.commons.util.SnowflakeUtil;
import com.woniu.form.AddPointForm;
import com.woniu.form.UpdateAdminInfoForm;
import com.woniu.zsd.commons.core.model.Result;
import com.woniu.zsd.commons.exception.ZsdException;
import com.woniu.zsd.merchant.client.ZsdMerchantClient;
import com.woniu.zsd.order.config.MyWebSocketHandler;
import com.woniu.zsd.order.entity.OrderInfo;
import com.woniu.zsd.order.entity.OrderWaste;
import com.woniu.zsd.order.entity.Statistics;
import com.woniu.zsd.order.from.*;
import com.woniu.zsd.order.mapper.OrderInfoMapper;
import com.woniu.zsd.order.mapper.OrderWasteMapper;
import com.woniu.zsd.order.mapper.StatisticsMapper;
import com.woniu.zsd.order.service.IOrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.zsd.permission.entity.AdminInfo;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-27
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {

    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderWasteMapper orderWasteMapper;
    @Resource
    private StatisticsMapper statisticsMapper;
    @Resource
    private ZsdMerchantClient zsdMerchantClient;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private PermissionClient permissionClient;
    @Resource
    private MyWebSocketHandler myWebSocketHandler;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private UserClient userClient;



    @Override
    public Page<OrderInfo> findUserOrder(FindUserOrderFrom fof,Integer userId) {
        Page<OrderInfo> page = new Page<>(
                fof.getPageNum() == null ? 1 : fof.getPageNum(),
                fof.getPageSize() == null ? 5 : fof.getPageSize()
        );
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        if(fof.getCreateTime()!=null)
        {
            LocalDate parse = LocalDate.parse(fof.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            // 将 LocalDate 转换为当天的开始时间和结束时间
            LocalDateTime startOfDay = parse.atStartOfDay(); // 当天 00:00:00
            LocalDateTime endOfDay = parse.atTime(LocalTime.MAX); // 当天 23:59:59
            // 添加查询条件：createTime 在 [startOfDay, endOfDay] 范围内
            wrapper.between("creat_time", startOfDay, endOfDay);
        }
        if(fof.getOrderState()!=null){
            wrapper.eq("order_state",fof.getOrderState());
        }
        Page<OrderInfo> orderInfoPage = orderInfoMapper.selectPage(page, wrapper);

        return orderInfoPage;
    }

    @Override
    public Page<OrderInfo> findAllOrder(FindAllOrderFrom faf) {
        Page<OrderInfo> page = new Page<>(
                faf.getPageNum() == null ? 1 : faf.getPageNum(),
                faf.getPageSize() == null ? 5 : faf.getPageSize()
        );
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        if(faf.getOrderState()!=null){
            wrapper.eq("order_state",faf.getOrderState());
        }
        if(faf.getSiteId()!=null){
            wrapper.eq("site_id",faf.getSiteId());
        }
        if(faf.getUserPhone()!=null&&faf.getUserPhone()!=""){
            wrapper.eq("user_phone",faf.getUserPhone());
        }
        if(faf.getWorkName()!=null&&faf.getWorkName()!=""){
            wrapper.eq("work_name",faf.getWorkName());
        }
        LocalDateTime startTime=null;
        LocalDateTime endTime=null;
        if(faf.getStartTime()!=null)startTime = DateUtils.parseToLocalDateTime(faf.getStartTime());
        if(faf.getEndTime()!=null) endTime = DateUtils.parseToLocalDateTime(faf.getEndTime());
        if (startTime != null && endTime != null) {
            // 时间范围查询
            wrapper.between("end_time", startTime, endTime);
        } else if (startTime != null) {
            // 只有开始时间：查询大于等于开始时间的数据
            wrapper.ge("end_time", startTime);
        } else if (endTime != null) {
            // 只有结束时间：查询小于等于结束时间的数据
            wrapper.le("end_time", endTime);
        }
        Page<OrderInfo> orderInfoPage = orderInfoMapper.selectPage(page, wrapper);
        return orderInfoPage;
    }

    @Override
    public Page<OrderInfo> findWorkOrder(FindWorkOrderFrom fwf,Integer id) {
        Page<OrderInfo> page = new Page<>(
                fwf.getPageNum() == null ? 1 : fwf.getPageNum(),
                fwf.getPageSize() == null ? 5 : fwf.getPageSize()
        );
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("work_id",id);
        if(fwf.getOrderState()!=null){
            wrapper.eq("order_state",fwf.getOrderState());
        }

        LocalDateTime startTime=null;
        LocalDateTime endTime=null;
        if(fwf.getStartTime()!=null)startTime = DateUtils.parseToLocalDateTime(fwf.getStartTime());
        if(fwf.getEndTime()!=null) endTime = DateUtils.parseToLocalDateTime(fwf.getEndTime());
        if (startTime != null && endTime != null) {
            // 时间范围查询
            wrapper.between("start_time", startTime, endTime);
        } else if (startTime != null) {
            // 只有开始时间：查询大于等于开始时间的数据
            wrapper.ge("start_time", startTime);
        } else if (endTime != null) {
            // 只有结束时间：查询小于等于结束时间的数据
            wrapper.le("start_time", endTime);
        }
        Page<OrderInfo> i = orderInfoMapper.selectPage(page, wrapper);
        return i;
    }

    @Transactional
    @Override
    public void userCreatOrder(UserCreatOrderFrom uof,Integer id) throws Exception {
        //用户创建订单
        OrderInfo info = new OrderInfo();
        String s = SnowflakeUtil.autoId();
        info.setOrderNumber(s);
        info.setCreatTime(LocalDateTime.now());
        info.setUserAddress(uof.getUserAddressId());
        info.setStartTime(DateUtils.parseToLocalDateTime(uof.getStartTime()));
        info.setUserPhone(uof.getUserPhone());
        info.setUserName(uof.getUserName());
        info.setUserId(id);
        List<OrderWaste> wastes = new ArrayList<>();

        if(uof.getOrderWastes()!=null||!uof.getOrderWastes().isEmpty()){
            List<UserCreatOrderFrom.OrderWasteFrom> wastesInfo = uof.getOrderWastes();
            for (UserCreatOrderFrom.OrderWasteFrom orderWasteFrom : wastesInfo) {
                OrderWaste orderWaste = new OrderWaste();
                orderWaste.setWasteInfo(orderWasteFrom.getWasteInfo());
                orderWaste.setWasteImage(orderWasteFrom.getWasteImage());
                orderWaste.setOrderNum(s);
                wastes.add(orderWaste);
            }
        }
        //调用通过地址id查询经纬度功能
        UserAddress data1 = userClient.selUserAddressById(uof.getUserAddressId()).getData();
        //调用通过经纬度查询附件站点方法
        Result<List<Integer>> result = zsdMerchantClient.recentSiteId(data1.getLongitude(), data1.getLatitude());
        if(result.getData() ==null&&result.getData().isEmpty()){
            //附近没有站点让商家判断是否接单
            orderInfoMapper.insert(info);
            myWebSocketHandler.sendPointToPointMessage("1","有新的回收订单请注意处理");
            return;
        }
        Integer integer = result.getData().get(0);
        //将其他距离的站点id存储到redis中
        List<String> siteList = new ArrayList<>();
        for (int i = 1; i < result.getData().size(); i++) {
            siteList.add(String.valueOf(result.getData().get(i)));
        }
        System.out.println(siteList);
        if (!siteList.isEmpty()) stringRedisTemplate.opsForList().rightPushAll(RedisKey.SITA_LIST(s),siteList);

        List<AdminInfo> data = permissionClient.selAdminInfoById(integer, -1, 1, 1, "-1").getData().getList();
        AdminInfo adminInfo = data.get(0);
        info.setDirectorName(adminInfo.getName());
        info.setDirectorPhone(adminInfo.getPhone());
        info.setSiteId(integer);
        info.setOrderState(7);
        orderInfoMapper.insert(info);
        if(!wastes.isEmpty()){
            orderWasteMapper.insertBatch(wastes);
        }
        //将订单信息放入消息队列站点没有接单换个站点处理
        rabbitTemplate.convertAndSend("site-expired-queue",s);

        //消息推送给站点
        myWebSocketHandler.sendPointToPointMessage(String.valueOf(adminInfo.getAdminId()),"有新的回收订单请注意处理");

    }

    @Override//取消订单方法
    public void cancelOrder(CancelOrderFrom cof) throws Exception {
        RLock lock = redissonClient.getFairLock(cof.getOrderNumber());

        try {
            lock.lock(5,TimeUnit.SECONDS);
            OrderInfo order_num = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().in("order_number", cof.getOrderNumber()));
            if(order_num==null) throw new ZsdException("订单不存在",500);
            Integer orderState = order_num.getOrderState();
            if(orderState==2||orderState==5||orderState==6)throw new ZsdException("订单状态已完成&已取消",500);
            UpdateWrapper<OrderInfo> wrapper = new UpdateWrapper<>();
            wrapper.eq("order_number",cof.getOrderNumber())
                    .set("order_state",6)
                    .set("remarks",cof.getRemarks());
            orderInfoMapper.update(null,wrapper);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            lock.unlock();
        }

    }

    @Override
    public void siteAllocationOrder(SiteAllocationOrderFrom sof) throws Exception {
        //对分配订单操作进行加锁，锁订单号
        RLock lock = redissonClient.getLock(sof.getOrderNumber());

        try {
            lock.lock(5,TimeUnit.SECONDS);
            Result<PageInfo<AdminInfo>> pageInfoResult = permissionClient.selAdminInfoById(null,sof.getWorkId(),1,1,"-1");
            PageInfo<AdminInfo> data = pageInfoResult.getData();
            AdminInfo info = new AdminInfo();
            if (data != null && data.getList() != null && !data.getList().isEmpty()) {
                List<AdminInfo> adminInfoList = data.getList();
                for (AdminInfo adminInfo : adminInfoList) {
                    // 打印或处理每个 AdminInfo 对象
                    info.setAdminId(adminInfo.getAdminId());
                    info.setName(adminInfo.getName());
                    info.setPhone(adminInfo.getPhone());
                    info.setAdminId(adminInfo.getAdminId());
                }
            } else {
                throw new Exception("未查找到工作人员信息");
            }
            OrderInfo number = orderInfoMapper.findOrderByNumber(sof.getOrderNumber());
            if (number.getOrderState()!=7)throw new ZsdException("订单状态异常",500);

            orderInfoMapper.update(null,new UpdateWrapper<OrderInfo>()
                    .eq("order_number",sof.getOrderNumber())
                    .set("work_phone",info.getPhone())
                    .set("work_name",info.getName())
                    .set("work_id",info.getAdminId())
                    .set("order_state",4));
            myWebSocketHandler.sendPointToPointMessage(String.valueOf(info.getAdminId()),"你有新的订单需要处理");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }


    }

    @Override
    public void workUpdateOrderStatus(String orderNum, Integer id) throws Exception {
        RLock lock = redissonClient.getLock(orderNum);

        try {
            lock.lock(5,TimeUnit.SECONDS);
            OrderInfo order = orderInfoMapper.findOrderByNumber(orderNum);
            if(order.getOrderState()!=4)throw new ZsdException("状态异常",500);
            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setOrderNumber(orderNum);
            orderInfo.setWorkId(id);
            orderInfoMapper.updateState(orderNum);
            UpdateAdminInfoForm form = new UpdateAdminInfoForm();
            form.setAdminId(id);
            form.setState("2");
            permissionClient.updateAdminInfo(form);
        } finally {
            lock.unlock();
        }
    }

    @Transactional
    @Override
    public void siteUpdateOrder(String orderNumber) throws Exception {
        OrderInfo orderInfo = orderInfoMapper.findOrderByNumber(orderNumber);
        if (orderInfo==null)throw new ZsdException("订单不存在",500);
        if(orderInfo.getOrderState()!=2)throw new ZsdException("订单状态异常",500);
        OrderInfo info = new OrderInfo();
        info.setOrderNumber(orderNumber);
        info.setEndTime(LocalDateTime.now());
        orderInfoMapper.updateStateByOrderNumber(info);
        //获取这个订单的废品信息并统计
        List<OrderWaste> orderWastes = orderWasteMapper.findOrderWasteByOrderNumber(orderNumber);

        //将废品信息保存到统计表中
        List<Statistics> statisticsList = new ArrayList<>();
            for (OrderWaste orderWaste : orderWastes) {
            OrderWaste waste = new OrderWaste();
            waste.setSasteAllPrice(orderWaste.getSasteAllPrice());
            waste.setWeight(orderWaste.getWeight());
            waste.setSasteTypeId(orderWaste.getSasteTypeId());
            waste.setUnit(orderWaste.getUnit());
            //将废品信息保存到统计表中
                if(orderWaste.getSasteTypeId()!=null){
                    Statistics statisticss = new Statistics();
                    statisticss.setCreatTime(LocalDateTime.now());
                    statisticss.setPrice(waste.getSasteAllPrice());
                    statisticss.setQuantity(waste.getWeight());
                    statisticss.setQuantityUnit(waste.getUnit());
                    statisticss.setWasteTypeId(waste.getSasteTypeId());
                    statisticsList.add(statisticss);
                    String wasteTypeName = (String) stringRedisTemplate.opsForHash().get("waste_type", String.valueOf(waste.getSasteTypeId()));
                    //订单入库之后将对应废品类型排名+1
                    if (wasteTypeName!=null)stringRedisTemplate.opsForZSet().incrementScore("waste_type_search_count",wasteTypeName,1);
                }

            }
        statisticsMapper.insetWasteInfo(statisticsList);
        AddPointForm form = new AddPointForm();
        form.setId(String.valueOf(orderInfo.getUserId()));
        form.setType(1);
        form.setTotalAmount(orderInfo.getTotalAmount());
        userClient.addPointById(form);
        //订单入库后员工状态为空闲
        UpdateAdminInfoForm adminform = new UpdateAdminInfoForm();
        adminform.setAdminId(orderInfo.getWorkId());
        adminform.setState("1");
        permissionClient.updateAdminInfo(adminform);

    }

    @Override//管理员分配订单
    public void adminUpdateOrder(AdminUpdateOrder auo) throws IOException {
        //判断状态是否为新创建
        OrderInfo order = orderInfoMapper.findOrderByNumber(auo.getOrderNum());
        if(order.getOrderState()!=1)throw new ZsdException("该状态不能分配给其他站点",500);
        orderInfoMapper.adminUpdateOrder(auo);
        myWebSocketHandler.sendPointToPointMessage(String.valueOf(auo.getSiteId()),"你有新的订单消息请处理");
    }

    @Override//工作人员拒绝接单
    public void workNoOrder(String orderNumber) {
        orderInfoMapper.WorkUpdateState(orderNumber);
    }

    @Override
    public boolean isOrderFinish(Integer userId, Integer siteId) {
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId).eq("site_id",siteId);
        return orderInfoMapper.selectCount(wrapper) > 0;
    }


    @Transactional
    @Override
    public void confirmOrder(String orderNumber,Integer id) throws Exception {
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().in("order_number", orderNumber));
        if (orderInfo==null) throw new ZsdException("订单不存在",500);
        if (orderInfo.getOrderState()!=3)throw new ZsdException("订单已确认",500);
        if (!id.equals(orderInfo.getUserId()))throw new ZsdException("用户信息异常请重新登录",500);
        LocalDateTime now = LocalDateTime.now();
        orderInfoMapper.update(null,new UpdateWrapper<OrderInfo>().eq("order_number",orderNumber).set("update_time",now).set("order_state",2));
    }

}
